package com.term.dao;

import com.term.domain.BaseDomain;
import com.term.domain.utils.DomainPage;
import com.term.domain.common.Condition;

import java.util.List;
import java.util.Map;

/**
 * Created by chenGang on 2017/1/5.
 */
public interface IBaseDao<T extends BaseDomain> {

    public enum SortBy {
        DESC,
        ASC
    }

    /**
     * test <a href="ChengTaoYuan"></a>
     *
     * 如果你怀疑当前被管理的实体已经不是数据库中最新的数据，你可以通过refresh()方法刷新实体，
     * 容器会把数据库中的新值重写进实体。这种情况一般发 生在你获取了实体之后，有人更新了数据库中的记录，
     * 这时你需要得到最新的数据。
     *
     * @param t 实体
     * @return
     */
    public T refresh(T t);

    /**
     * test <a href="ChengTaoYuan"></a>
     *
     * 保存对象
     * 当该对象是已持久化的对象，既可以完成对已有对象的数据更新
     * 当该对象不是已持久化的对象，既是插入数据
     *
     * @param t
     * @return
     */
    public T save(T t);

    /**
     * test <a href="ChenGang"></a>
     *
     * 根据对象的ID查询对象
     *
     * @param clazz 实体class
     * @param id    实体id
     * @return
     */
    public T getEntityById(Class<T> clazz, Object id);

    /**
     * test <a href="ChenGang"></a>
     *
     * 根据对象的属性名和值完全匹配查询一个实体
     *
     * @param clazz
     * @param fieldName
     * @param fieldValue
     * @return
     */
    public T getEntityByField(Class<T> clazz, String fieldName, Object fieldValue);

    /**
     * test <a href="MaEnJie"></a>
     *
     * 根据对象的属性名和值完全匹配查询一个或多个实体
     *
     * @param clazz      实体class
     * @param fieldName  查询字段
     * @param fieldValue 查询字段的属性值
     * @return
     */
    public List<T> getEntitiesByField(Class<T> clazz, String fieldName, Object fieldValue);

    /**
     * test <a href="MaEnJie"></a>
     *
     * 根据对象的属性集合查询对象 ,每个属性值采用精确匹配
     *
     * @param clazz             对象类
     * @param fieldNameValueMap 对象属性名称值对集合
     * @return
     */
    public List<T> getEntitiesByFieldList(Class<T> clazz, Map<String, Object> fieldNameValueMap);

    /**
     * test <a href="ChengTaoYuan"></a>
     *
     * 根据对象属性名及名称完全匹配查询符合条件的实体记录总数
     *
     * @param clazz
     * @param fieldName  做完全匹配查询的属性名
     * @param fieldValue 做完全匹配查询的属性值
     * @return
     */
    public long getEntityTotalCount(Class<T> clazz, String fieldName, Object fieldValue);

    /**
     * test <a href="ChengTaoYuan"></a>
     *
     * 获取指定实体的记录数量
     *
     * @param clazz 实体class
     * @return
     */
    public long getEntityTotalCount(Class<T> clazz);

    /**
     * test <a href="ChenGang"></a>
     *
     * 通过多条件查询实体记录数量
     *
     * @param clazz
     * @param fieldNameValueMap
     * @return
     */
    public long getEntityTotalCount(Class<T> clazz, Map<String, Object> fieldNameValueMap);

    /**
     * test <a href="ChenGang"></a>
     *
     * 获取所有的实体对象 ，由于本方法没有采用分页，所以当表数据过大时谨慎使用
     *
     * @param clazz 对象类
     * @return
     */
    public List<T> getAllEntities(Class<T> clazz);

    /**
     * test <a href="MaEnJie"></a>
     *
     * 分页获取所有的实体对象
     *
     * @param clazz     对象类
     * @param pageIndex 当前页
     * @param pageSize  显示条数
     * @return
     */
    public DomainPage getAllEntitiesByPage(Class<T> clazz, int pageIndex, int pageSize);

    /**
     * test <a href="MaEnJie"></a>
     *
     * 分页获取所有的实体对象
     *
     * @param clazz        对象类
     * @param pageIndex    当前页
     * @param pageSize     显示条数
     * @param orderBy 排序字段
     * @param sortBy       倒叙还是正序DESC,ASC
     * @return
     */
    public DomainPage getAllEntitiesByPage(Class<T> clazz, int pageIndex, int pageSize, String orderBy, SortBy sortBy);

    /**
     * test <a href="ChengTaoYuan"></a>
     *
     * 根据对象属性，分页获取所有匹配的实体对象，默认按数据的更新时间排序
     *
     * @param clazz      对象类
     * @param filedName  做完全匹配查询的属性名
     * @param filedValue 做完全匹配查询的属性值
     * @param pageIndex  当前页
     * @param pageSize   显示条数
     * @return
     */
    public DomainPage getEntitiesByPage(Class<T> clazz, String filedName, Object filedValue, int pageIndex, int pageSize);

    /**
     * test <a href="ChengTaoYuan"></a>
     *
     * 根据对象的属性集合查询对象 ,每个属性值采用精确匹配
     *
     * @param clazz             对象类
     * @param fieldNameValueMap 对象属性名称值对集合
     * @return
     */
    public DomainPage getEntitiesPagesByFieldList(Class<T> clazz, Map<String, Object> fieldNameValueMap, int pageIndex, int pageSize);

    /**
     * test <a href="ChenGang"></a>
     *
     * 根据对象的属性集合查询对象，且根据参数进行升降序排序，每个属性值采用精确匹配
     *
     * @param clazz             对象类
     * @param fieldNameValueMap 做完全匹配查询的属性名/属性值键值对
     * @param orderByFiledName  排序属性
     * @param sortBy            desc,asc
     * @return
     */
    public List<T> getEntitiesByFieldList(Class<T> clazz, Map<String, Object> fieldNameValueMap, String orderByFiledName, SortBy sortBy);

    /**
     * test <a href="ChenGang"></a>
     *
     * 根据对象的属性集合查询对象，且根据参数进行升降序排序，每个属性值采用精确匹配
     *
     * @param clazz             对象类
     * @param fieldNameValueMap 做完全匹配查询的属性名/属性值键值对
     * @param orderByFiledName  排序属性
     * @param sortBy            倒叙还是正序DESC,ASC
     * @param pageIndex         当前页
     * @param pageSize          显示条数
     * @return
     */
    public DomainPage getEntitiesPagesByFieldList(Class<T> clazz, Map<String, Object> fieldNameValueMap, String orderByFiledName, SortBy sortBy, int pageIndex, int pageSize);

    /**
     * test <a href="MaEnJie"></a>
     *
     * 功能：根据查询条件来动态选择查询方式，并返回指定实体的分页列表（如果查询条件为空，则进行全局查询）
     *
     * @param clazz             实体类
     * @param fieldNameValueMap 组合查询条件
     * @param orderBy           根据哪个字段进行排序
     * @param sortBy            DESC：降序，ASC：升序
     * @param pageIndex         页面索引
     * @param pageSize          分页大小
     * return                   元素分页列表
     */
    public DomainPage queryEntitiesPagesByFieldList(Class<T> clazz, Map<String, Object> fieldNameValueMap, String orderBy, SortBy sortBy, int pageIndex, int pageSize);

    /**
     * test <a href="MaEnJie"></a>
     *
     * 根据条件分页查询
     *
     * @param clazz
     * @param condition
     * @param pageIndex
     * @param pageSize
     * @return
     */
    public DomainPage getEntitiesPagesByCondition(Class<T> clazz, Condition condition, int pageIndex, int pageSize);

    /**
     * test <a href="ChengTaoYuan"></a>
     * <p>
     * 根据条件分页查询并按着自定义的orderBy排序
     *
     * @param clazz     实体class
     * @param condition 查询条件
     * @param orderBy   根据哪个字段进行排序
     * @param sortBy    降序还是升序
     * @param pageIndex 页面索引
     * @param pageSize  分页大小
     * @return
     */
    public DomainPage getEntitiesPagesByCondition(Class<T> clazz, Condition condition, String orderBy, SortBy sortBy, int pageIndex, int pageSize);

    /**
     * test <a href="ChenGang"></a>
     *
     * 根据条件返回列表
     * @param clazz     实体class
     * @param condition 查询条件
     * @return
     */
    public List<T> getEntitiesByCondition(Class<T> clazz, Condition condition);

    /**
     * test <a href="MaEnJie"></a>
     *
     * 根据条件返回列表并按着自定义的orderBy排序
     * @param clazz     实体class
     * @param condition 查询条件
     * @param orderBy   根据哪个字段进行排序
     * @param sortBy    降序还是升序
     * @return
     */
    public List<T> getEntitiesByCondition(Class<T> clazz, Condition condition, String orderBy, SortBy sortBy);

    /**
     * test <a href="ChenGang"></a>
     *
     * 根据对象的属性集合查询对象，且根据参数进行升降序排序，每个属性值采用模糊匹配
     * <p>
     * 备注：修复非模糊查询字段使用模糊查询会出现错误的bug
     *
     * @param clazz             对象类
     * @param fieldNameValueMap 做完全匹配查询的属性名/属性值键值对
     * @param orderBy           排序属性
     * @param sortBy            倒叙还是正序DESC,ASC
     * @param pageIndex         当前页
     * @param pageSize          显示条数
     * @return
     */
    public DomainPage findEntitiesPagesByFieldList(Class<T> clazz, Map<String, Object> fieldNameValueMap, String orderBy, SortBy sortBy, int pageIndex, int pageSize);
}
